package cn.maxmc.murderaddons.task

import cn.maxmc.murderaddons.MurderAddons
import cn.maxmc.murderaddons.machine.BaseMachine
import cn.maxmc.murderaddons.settings
import org.bukkit.Bukkit
import org.bukkit.boss.BarColor
import org.bukkit.boss.BarStyle
import org.bukkit.configuration.serialization.ConfigurationSerializable
import org.bukkit.configuration.serialization.SerializableAs
import org.bukkit.entity.Player
import org.bukkit.scheduler.BukkitTask
import plugily.projects.murdermystery.arena.Arena
import plugily.projects.murdermystery.arena.ArenaRegistry
import kotlin.collections.ArrayList
import kotlin.collections.HashMap

@Suppress("UNCHECKED_CAST")
@SerializableAs("ArenaTask")
data class ArenaTask(val arena: Arena, val machines: ArrayList<BaseMachine>): ConfigurationSerializable {
    val task = HashMap<Player,ArenaPlayerTask>()
    constructor(map: Map<String,Any>): this(ArenaRegistry.getArena(map["arena"] as String),ArrayList(map["machines"] as List<BaseMachine>))

    private val processBar = Bukkit.createBossBar("任务进度",BarColor.WHITE,BarStyle.SOLID)

    var updater: BukkitTask? = null

    fun updateBar() {
        val process = getTotalProcess()
        processBar.progress = process
        if(process >= 1.0) {
            arena.murdererList.forEach {
                it.damage(100.0)
            }
        }
    }

    private fun initBar() {
        arena.players.forEach {
            processBar.addPlayer(it)
            processBar.isVisible = true
        }
        updater = Bukkit.getScheduler().runTaskTimer(MurderAddons.plugin,::updateBar,0L,10L)
    }

    fun getTotalProcess(): Double {
        val total = task.size
        var current = 0.0

        task.forEach { (_, player) ->
            current += player.getProcess()
        }

        return current/total.toDouble()
    }

    /**
     * 生成该游戏的任务,应在游戏开始时被调用
     */
    fun generateTask() {
        reset()
        val common = machines.filter { it.taskType == TaskType.COMMON }.toMutableList()

        val temp = ArrayList<BaseMachine>()
        repeat(settings.getInt("task.common")) {
            val task = common.random()
            temp.add(task)
            common.remove(task)
        }

        // filter the murder
        val players = arena.players.filter { !(arena.murdererList.contains(it)) }

        players.forEach {
            val playerTemp = ArrayList<BaseMachine>(temp)
            val short = machines.filter { it.taskType == TaskType.SHORT }.toMutableList()
            val long = machines.filter { it.taskType == TaskType.LONG }.toMutableList()
            repeat(settings.getInt("task.short")) {
                val task = short.random()
                temp.add(task)
                short.remove(task)
            }
            repeat(settings.getInt("task.long")) {
                val task = long.random()
                temp.add(task)
                short.remove(task)
            }

            playerTemp.forEach { m -> m.addTask(it) }

            task[it] = ArenaPlayerTask(it,playerTemp)
        }
        initBar()
    }

    fun reset() {
        if(updater != null) {
            updater!!.cancel()
            updater = null
        }
        processBar.removeAll()
        machines.forEach(BaseMachine::reset)
        task.clear()
    }

    override fun serialize(): MutableMap<String, Any> {
        return mutableMapOf(
            "arena" to arena.id,
            "machines" to machines
        )
    }
}
